package com.ymy.thinking.in.spring.dependency.injection.annotation;

import com.ymy.thinking.in.spring.dependency.injection.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.AnnotationConfigUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;

import javax.inject.Inject;

/**
 * 自定义 DI 依赖注入示例
 *
 * @author Ringo
 * @date 2021/10/18 22:14
 */
public class CustomizeDIAnnotationDemo {

    @Autowired
    public User user;

    @Injected
    public User user1;

    @Inject
    public User user2;

    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext =
                new AnnotationConfigApplicationContext(CustomizeDIAnnotationDemo.class);
        CustomizeDIAnnotationDemo demo = applicationContext.getBean(CustomizeDIAnnotationDemo.class);
        System.out.println(demo.user);
        System.out.println(demo.user1);
        System.out.println(demo.user2);
    }

    @Bean
    public User user() {
        return new User("ls", 12);
    }

    /**
     * {@link AnnotationConfigUtils#AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME}
     * <p>
     * 静态注入 Bean, 脱离上层配置类而提前注册。
     * <p>
     * 非静态注入 Bean, 依赖上层配置类而注册Bean。
     */
/*    @Bean(name = AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)
    public static AutowiredAnnotationBeanPostProcessor beanPostProcessor() {
        AutowiredAnnotationBeanPostProcessor beanPostProcessor =
                new AutowiredAnnotationBeanPostProcessor();
        // 替换原有的注解处理, 使用新注解 @Injected
        Set<Class<? extends Annotation>> set = Stream.of(Autowired.class, Inject.class, Injected.class).collect(Collectors.toSet());
        beanPostProcessor.setAutowiredAnnotationTypes(set);
        return beanPostProcessor;
    }*/

    /**
     * 扩展DI的最优方式: 这样实现新旧注解都可以使用
     * <p>
     * static 静态注入会对 Bean 注入优先级做提升
     */
    @Bean
    @Order(Ordered.LOWEST_PRECEDENCE - 3)
    public static AutowiredAnnotationBeanPostProcessor beanPostProcessor() {
        AutowiredAnnotationBeanPostProcessor beanPostProcessor =
                new AutowiredAnnotationBeanPostProcessor();
        // 替换原有的注解处理, 使用新注解 @Injected
        beanPostProcessor.setAutowiredAnnotationType(Injected.class);
        return beanPostProcessor;
    }

}
